<template>
  <el-row>
    <el-tabs v-model="tabName" style="width: 100%" @tab-click="handleClick">
      <el-tab-pane label="运行状态" name="property">
        <el-row>
          <el-col :span="3">
            <avue-tree ref="tree"
                       :option="optionTree"
                       :data="dataTree"
                       v-model="formTree"
                       :filter-node-method="filterNodeMethod"
                       @node-click="nodeClickTree">
              <template #default="{ node, data }">
              <span class="custom-tree-node">
                <span v-if="data.isDefault === 1">默认模块</span>
                <span v-else>{{ node.label }}</span>
              </span>
              </template>
            </avue-tree>
          </el-col>
          <el-col :span="1">
          </el-col>
          <el-col :span="20">
            <avue-crud ref="property"
                       :option="optionProperty"
                       :data="dataProperty"
                       v-model="formProperty"
                       :table-loading="loading">
              <template #menu-left="{}">
                <el-input v-model="searchPropertyVal" style="width: 240px"
                          placeholder="输入 属性名称 或 属性标识符 查询"/>
                <el-button type="primary" icon="el-icon-search" class="margin-node" @click="propertySearch">搜 索
                </el-button>
                <el-button icon="el-icon-delete" class="margin-node" @click="clearPropertySearch">清 空</el-button>
                <el-button class="margin-node" @click="propertyAutoReload">
                  <template v-if="reloading">
                    <el-icon class="is-loading margin-icon">
                      <Loading/>
                    </el-icon>
                    关闭刷新
                  </template>
                  <template v-else>
                    <el-icon class="margin-icon">
                      <Sort/>
                    </el-icon>
                    自动刷新
                  </template>
                </el-button>
              </template>
              <template #menu="{row,index,size}">
                <el-button text type="primary"
                           icon="el-icon-box"
                           @click="viewPropertyHistoryData(row)">历史数据
                </el-button>
              </template>
              <template #identifier="{ row }">
                <el-tag type="primary" style="cursor: pointer" @click="viewPropertyHistoryData(row)">
                  {{ row.identifier }}
                </el-tag>
              </template>
            </avue-crud>
            <el-dialog v-model="visible" title="查看物模型数据" width="850">
              <el-row>
                <el-select
                    v-model="propertyTimeType"
                    clearable
                    placeholder="请选择时间区间"
                    @change="propertyTimeListChange"
                    style="width: 150px"
                >
                  <el-option
                      v-for="item in timeLists"
                      :key="item.value"
                      :label="item.label"
                      :value="item.value"
                  />
                </el-select>
                <el-date-picker
                    v-if="propertyTimeType === 'custom'"
                    v-model="propertyTimeRange"
                    type="datetimerange"
                    start-placeholder="开始时间"
                    end-placeholder="结束时间"
                    @change="propertyTimeRangeChange"
                    format="YYYY-MM-DD HH:mm:ss"
                    date-format="YYYY/MM/DD ddd"
                    time-format="A hh:mm:ss"
                    class="margin-node"
                    style="width: 350px"
                />
                <el-button
                    icon="el-icon-delete"
                    @click="clearPropertyHistorySearch"
                    class="margin-node">
                  清 空
                </el-button>
              </el-row>
              <el-row>
                <avue-crud ref="propertyHistory"
                           v-model:page="pagePropertyHistory"
                           :option="optionPropertyHistory"
                           :data="dataPropertyHistory"
                           :table-loading="loading"
                           @current-change="currentChangePropertyHistory"
                           @size-change="sizeChangePropertyHistory"
                           @refresh-change="refreshChangePropertyHistory">
                </avue-crud>
              </el-row>
            </el-dialog>
          </el-col>
        </el-row>
      </el-tab-pane>
      <el-tab-pane label="命令调用" name="command">
        <el-row>
          <el-select
              v-model="commandBlockId"
              clearable
              placeholder="请选择模块"
              @change="blockChangeCommand"
              style="width: 180px"
          >
            <el-option
                v-for="item in dataTree"
                :key="item.value"
                :label="item.isDefault === 1 ? '默认模块': item.title"
                :value="item.value"
            />
          </el-select>
          <el-select
              v-model="commandIdentifierId"
              clearable
              placeholder="请选择标识符"
              @change="identifierChangeCommand"
              class="margin-node"
              style="width: 250px"
          >
            <el-option
                v-for="item in commandIdentifierData"
                :key="item.identifier"
                :label="item.name"
                :value="item.identifier"
            />
          </el-select>
          <el-select
              v-model="commandTimeType"
              clearable
              placeholder="请选择时间区间"
              @change="commandTimeListChange"
              class="margin-node"
              style="width: 150px"
          >
            <el-option
                v-for="item in timeLists"
                :key="item.value"
                :label="item.label"
                :value="item.value"
            />
          </el-select>
          <el-date-picker
              v-if="commandTimeType === 'custom'"
              v-model="commandTimeRange"
              type="datetimerange"
              start-placeholder="开始时间"
              end-placeholder="结束时间"
              @change="commandTimeRangeChange"
              format="YYYY-MM-DD HH:mm:ss"
              date-format="YYYY/MM/DD ddd"
              time-format="A hh:mm:ss"
              class="margin-node"
              style="width: 350px"
          />
          <el-button
              icon="el-icon-delete"
              @click="clearCommandSearch"
              class="margin-node">
            清 空
          </el-button>
        </el-row>
        <el-row>
          <avue-crud ref="command"
                     v-model:page="pageCommand"
                     :option="optionCommand"
                     :data="dataCommand"
                     v-model="formCommand"
                     :table-loading="loading"
                     @current-change="currentChangeCommand"
                     @size-change="sizeChangeCommand"
                     @refresh-change="refreshChangeCommand">
          </avue-crud>
        </el-row>
      </el-tab-pane>
      <el-tab-pane label="事件管理" name="event">
        <el-row>
          <el-select
              v-model="eventBlockId"
              clearable
              placeholder="请选择模块"
              @change="blockChangeEvent"
              style="width: 180px"
          >
            <el-option
                v-for="item in dataTree"
                :key="item.value"
                :label="item.isDefault === 1 ? '默认模块': item.title"
                :value="item.value"
            />
          </el-select>
          <el-select
              v-model="eventIdentifierId"
              clearable
              placeholder="请选择标识符"
              @change="identifierChangeEvent"
              class="margin-node"
              style="width: 250px"
          >
            <el-option
                v-for="item in eventIdentifierData"
                :key="item.identifier"
                :label="item.name"
                :value="item.identifier"
            />
          </el-select>
          <el-select
              v-model="eventTypeId"
              clearable
              placeholder="请选择事件类型"
              @change="eventTypeChange"
              class="margin-node"
              style="width: 150px"
          >
            <el-option
                v-for="item in eventTypes"
                :key="item.value"
                :label="item.label"
                :value="item.value"
            />
          </el-select>
          <el-select
              v-model="eventTimeType"
              clearable
              placeholder="请选择时间区间"
              @change="eventTimeListChange"
              class="margin-node"
              style="width: 150px"
          >
            <el-option
                v-for="item in timeLists"
                :key="item.value"
                :label="item.label"
                :value="item.value"
            />
          </el-select>
          <el-date-picker
              v-if="eventTimeType === 'custom'"
              v-model="eventTimeRange"
              type="datetimerange"
              start-placeholder="开始时间"
              end-placeholder="结束时间"
              @change="eventTimeRangeChange"
              format="YYYY-MM-DD HH:mm:ss"
              date-format="YYYY/MM/DD ddd"
              time-format="A hh:mm:ss"
              class="margin-node"
              style="width: 350px"
          />
          <el-button
              icon="el-icon-delete"
              @click="clearEventSearch"
              class="margin-node">
            清 空
          </el-button>
        </el-row>
        <el-row>
          <avue-crud ref="event"
                     v-model:page="pageEvent"
                     :option="optionEvent"
                     :data="dataEvent"
                     v-model="formEvent"
                     :table-loading="loading"
                     @current-change="currentChangeEvent"
                     @size-change="sizeChangeEvent"
                     @refresh-change="refreshChangeEvent">
          </avue-crud>
        </el-row>
      </el-tab-pane>
    </el-tabs>
  </el-row>
  <el-row>
  </el-row>
</template>

<script>
import {validatenull} from "@/utils/validate";
import { dataTypeName, fieldTypeName, optionDeviceTree } from "@/option/iot/function";
import {optionProperty, optionPropertyHistory, optionCommand, optionEvent} from "@/option/iot/device";
import {dataPublishedByKey} from "@/api/iot/product/version";
import {
  getPropertyLatest,
  getPropertyHistory,
  getCommandHistory,
  getEventHistory,
} from "@/api/iot/device/sequence";
import func from "@/utils/func";

export default {
  name: 'deviceFunction',
  props: {
    productKey: String,
    deviceId: String,
  },
  data() {
    return {
      tabName: "property",
      activeName: '默认模块',
      blockId: '',
      propertyIdentifierId: '',
      propertyTimeType: '',
      commandBlockId: '',
      commandIdentifierId: '',
      commandIdentifierData: [],
      commandTimeType: '',
      eventBlockId: '',
      eventIdentifierId: '',
      eventIdentifierData: [],
      eventTypeId: '',
      eventTimeType: '',
      formProperty: {},
      formCommand: {},
      formEvent: {},
      tsl: "",
      detail: {},
      query: {},
      queryPropertyHistory: {},
      queryCommand: {},
      queryEvent: {},
      search: {},
      searchPropertyVal: '',
      searchCommand: {},
      searchEvent: {},
      pagePropertyHistory: {
        pageSize: 10,
        currentPage: 1,
        total: 0
      },
      pageCommand: {
        pageSize: 10,
        currentPage: 1,
        total: 0
      },
      pageEvent: {
        pageSize: 10,
        currentPage: 1,
        total: 0
      },
      loading: false,
      reloading: false,
      timer: null,
      visible: false,
      versionId: "",
      versionSelect: [],
      snapshotMode: true,
      optionProperty: optionProperty,
      optionPropertyHistory: optionPropertyHistory,
      optionCommand: optionCommand,
      optionEvent: optionEvent,
      optionTree: optionDeviceTree,
      formBlock: {},
      formTree: {},
      formVersion: "",
      dataProperty: [],
      dataPropertyHistory: [],
      dataCommand: [],
      dataEvent: [],
      dataTree: [],
      dataSnapshot: {},
      propertySnapshot: [],
      commandSnapshot: [],
      eventSnapshot: [],
      blockSnapshot: [],
      eventTypes: [{
        label: '信息',
        value: 'info',
      }, {
        label: '告警',
        value: 'alert',
      }, {
        label: '故障',
        value: 'error',
      }],
      timeLists: [{
        label: '最近一小时',
        value: '1h',
      }, {
        label: '最近一天',
        value: '1d',
      }, {
        label: '最近一周',
        value: '1w',
      }, {
        label: '最近一个月',
        value: '1m',
      }, {
        label: '自定义区间',
        value: 'custom',
      }],
      timeRange: this.calculateTimeRange(),
      propertyTimeRange: this.calculateTimeRange(),
      commandTimeRange: this.calculateTimeRange(),
      eventTimeRange: this.calculateTimeRange(),
    };
  },
  mounted() {
    this.onLoadProperty();
  },
  watch: {
    deviceId() {
      if (!validatenull(this.deviceId) && this.dataProperty.length > 0) {
        // 匹配时序库中最新属性数据
        this.matchPropertyLatest(this.dataProperty);
      }
    }
  },
  methods: {
    handleClick(tab, event) {
      if (tab.paneName === "property") {
        this.matchPropertyLatest(this.dataProperty);
      } else if (tab.paneName === "command") {
        this.onLoadCommand(this.pageCommand);
      } else if (tab.paneName === "event") {
        this.onLoadEvent(this.pageEvent);
      }
    },
    nodeClickTree(data) {
      // 将模块名称赋值给activeName
      this.activeName = data.isDefault === 1 ? "默认模块" : data.title;
      // 将模块id赋值给blockId
      this.blockId = data.key;
      // 将模块属性赋值给dataProperty
      this.dataProperty = this.propertySnapshot.filter(item => item.blockId === data.key);
      // 匹配时序库中最新属性数据
      this.matchPropertyLatest(this.dataProperty);
    },
    filterNodeMethod(value, data) {
      if (!value) return true;
      return data.label.indexOf(value) !== -1;
    },
    viewPropertyHistoryData(row) {
      this.propertyIdentifierId = row.identifier;
      this.visible = true;
      this.onLoadPropertyHistory(this.pagePropertyHistory, this.queryPropertyHistory);
    },
    propertyAutoReload() {
      this.reloading = !this.reloading;
      if (this.reloading) {
        // 定时每秒执行刷新
        this.timer = setInterval(() => {
          this.onLoadProperty();
        }, 1000);
      } else {
        clearInterval(this.timer);
      }
    },
    propertySearch() {
      this.onLoadProperty();
    },
    clearPropertySearch() {
      this.searchPropertyVal = null;
      this.onLoadProperty();
    },
    clearPropertyHistorySearch() {
      this.propertyTimeType = '';
      this.propertyTimeRange = this.calculateTimeRange();
      this.queryPropertyHistory = {};
      this.onLoadPropertyHistory(this.pagePropertyHistory, this.queryPropertyHistory);
    },
    clearCommandSearch() {
      this.commandBlockId = '';
      this.commandIdentifierId = '';
      this.commandTimeType = '';
      this.commandTimeRange = this.calculateTimeRange();
      this.queryCommand = {};
      this.onLoadCommand(this.pageCommand, this.queryCommand);
    },
    clearEventSearch() {
      this.eventBlockId = '';
      this.eventIdentifierId = '';
      this.eventTypeId = '';
      this.eventTimeType = '';
      this.eventTimeRange = this.calculateTimeRange();
      this.queryEvent = {};
      this.onLoadEvent(this.pageEvent, this.queryEvent);
    },
    blockChangeCommand(value) {
      this.commandBlockId = value;
      this.commandIdentifierData = this.commandSnapshot.filter(item => item.blockId === value).map(item => {
        return {
          name: `${item.name} - ${item.identifier}`,
          identifier: item.identifier,
        }
      });
      if (this.commandIdentifierData.length > 0) {
        this.commandIdentifierId = this.commandIdentifierData[0].identifier;
        this.queryCommand = {
          ...this.queryCommand,
          identifier: this.commandIdentifierId,
        };
        this.onLoadCommand(this.pageCommand, this.queryCommand);
      }
    },
    identifierChangeCommand(value) {
      this.commandIdentifierId = value;
      this.queryCommand = {
        ...this.queryCommand,
        identifier: this.commandIdentifierId,
      };
      this.onLoadCommand(this.pageCommand, this.queryCommand);
    },
    propertyTimeListChange(value) {
      this.propertyTimeType = value;
      const timeList = this.buildTimeList(value);
      this.queryPropertyHistory = {
        ...this.queryPropertyHistory,
        timeList
      };
      this.onLoadPropertyHistory(this.pagePropertyHistory, this.queryPropertyHistory);
    },
    propertyTimeRangeChange(value) {
      this.propertyTimeRange = value;
      let timeList = [];
      if (!validatenull(value)) {
        timeList = [
          func.toLocalISOString(value[0]),
          func.toLocalISOString(value[1])
        ];
      }
      this.queryPropertyHistory = {
        ...this.queryPropertyHistory,
        timeList
      };
      this.onLoadPropertyHistory(this.pagePropertyHistory, this.queryPropertyHistory);
    },
    commandTimeListChange(value) {
      this.commandTimeType = value;
      const timeList = this.buildTimeList(value);
      this.queryCommand = {
        ...this.queryCommand,
        timeList
      };
      this.onLoadCommand(this.pageCommand, this.queryCommand);
    },
    commandTimeRangeChange(value) {
      this.commandTimeRange = value;
      let timeList = [];
      if (!validatenull(value)) {
        timeList = [
          func.toLocalISOString(value[0]),
          func.toLocalISOString(value[1])
        ];
      }
      this.queryCommand = {
        ...this.queryCommand,
        timeList
      };
      this.onLoadCommand(this.pageCommand, this.queryCommand);
    },
    eventTimeListChange(value) {
      this.eventTimeType = value;
      const timeList = this.buildTimeList(value);
      this.queryEvent = {
        ...this.queryEvent,
        timeList
      };
      this.onLoadEvent(this.pageCommand, this.queryEvent);
    },
    eventTimeRangeChange(value) {
      this.eventTimeRange = value;
      let timeList = [];
      if (!validatenull(value)) {
        timeList = [
          func.toLocalISOString(value[0]),
          func.toLocalISOString(value[1])
        ];
      }
      this.queryEvent = {
        ...this.queryEvent,
        timeList
      };
      this.onLoadEvent(this.pageCommand, this.queryEvent);
    },
    calculateTimeRange() {
      const today = new Date();
      const tomorrow = new Date();
      today.setHours(0, 0, 0, 0); // 当天0点
      tomorrow.setDate(tomorrow.getDate() + 1);
      tomorrow.setHours(0, 0, 0, 0); // 第二天0点
      return [today, tomorrow];
    },
    buildTimeList(value) {
      let timeList = [];
      if (!validatenull(value)) {
        // 获取当前时间
        const now = new Date();
        if (value === '1h') {
          // 最近一小时
          const oneHourAgo = new Date(now.getTime() - 60 * 60 * 1000);
          timeList = [oneHourAgo, now];
        } else if (value === '1d') {
          // 最近一天
          const oneDayAgo = new Date(now.getTime() - 24 * 60 * 60 * 1000);
          timeList = [oneDayAgo, now];
        } else if (value === '1w') {
          // 最近一周
          const oneWeekAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
          timeList = [oneWeekAgo, now];
        } else if (value === '1m') {
          // 最近一个月
          const oneMonthAgo = new Date(now.getFullYear(), now.getMonth() - 1, now.getDate());
          timeList = [oneMonthAgo, now];
        } else if (value === 'custom') {
          // 自定义区间
          timeList = [this.timeRange[0], this.timeRange[1]];
        } else {
          console.log('Unexpected value:', value);
        }
        timeList = [
          func.toLocalISOString(timeList[0]),
          func.toLocalISOString(timeList[1])
        ];
      }
      return timeList;
    },
    blockChangeEvent(value) {
      this.eventBlockId = value;
      this.eventIdentifierData = this.eventSnapshot.filter(item => item.blockId === value).map(item => {
        return {
          name: `${item.name} - ${item.identifier}`,
          identifier: item.identifier,
        }
      });
      if (this.eventIdentifierData.length > 0) {
        this.eventIdentifierId = this.eventIdentifierData[0].identifier;
        this.queryEvent = {
          ...this.queryEvent,
          identifier: this.eventIdentifierId,
        };
        this.onLoadEvent(this.pageCommand, this.queryEvent);
      }
    },
    identifierChangeEvent(value) {
      this.eventIdentifierId = value;
      this.queryEvent = {
        ...this.queryEvent,
        identifier: this.eventIdentifierId,
      };
      this.onLoadEvent(this.pageCommand, this.queryEvent);
    },
    eventTypeChange(value) {
      this.eventTypeId = value;
      this.queryEvent = {
        ...this.queryEvent,
        eventType: this.eventTypeId,
      };
      this.onLoadEvent(this.pageCommand, this.queryEvent);
    },
    currentChangePropertyHistory(currentPage) {
      this.pagePropertyHistory.currentPage = currentPage;
      this.onLoadPropertyHistory(this.pagePropertyHistory, this.queryPropertyHistory);
    },
    sizeChangePropertyHistory(pageSize) {
      this.pagePropertyHistory.pageSize = pageSize;
      this.onLoadPropertyHistory(this.pagePropertyHistory, this.queryPropertyHistory);
    },
    refreshChangePropertyHistory() {
      this.onLoadPropertyHistory(this.pagePropertyHistory, this.queryPropertyHistory);
    },
    currentChangeCommand(currentPage) {
      this.pageCommand.currentPage = currentPage;
      this.onLoadCommand(this.pageCommand, this.queryCommand);
    },
    sizeChangeCommand(pageSize) {
      this.pageCommand.pageSize = pageSize;
      this.onLoadCommand(this.pageCommand, this.queryCommand);
    },
    refreshChangeCommand() {
      this.onLoadCommand(this.pageCommand, this.queryCommand);
    },
    currentChangeEvent(currentPage) {
      this.pageEvent.currentPage = currentPage;
      this.onLoadEvent(this.pageEvent, this.queryEvent);
    },
    sizeChangeEvent(pageSize) {
      this.pageEvent.pageSize = pageSize;
      this.onLoadEvent(this.pageEvent, this.queryEvent);
    },
    refreshChangeEvent() {
      this.onLoadEvent(this.pageEvent, this.queryEvent);
    },
    matchPropertyLatest(data) {
      if (validatenull(this.deviceId)) {
        return;
      }
      getPropertyLatest(this.deviceId).then(res => {
        const latestData = res.data.data;
        this.dataProperty = data.map(item => {
          const property = latestData[item.identifier];
          if (!validatenull(property)) {
            item.actualValue = property;
          }
          return item;
        });
      });
    },
    onLoadProperty() {
      dataPublishedByKey(this.productKey).then(res => {
        this.dataSnapshot = res.data.data;
        // 判断需要查询的情况
        const propertySnapshot = !validatenull(this.searchPropertyVal) ?
            this.dataSnapshot.properties.filter(item =>
                item.name.includes(this.searchPropertyVal) || item.identifier.includes(this.searchPropertyVal)
            ) : this.dataSnapshot.properties;
        // 设置额外字段
        this.propertySnapshot = propertySnapshot.map(item => {
          return {
            ...item,
            fieldTypeName: fieldTypeName(item),
            dataTypeName: dataTypeName(item)
          }
        });
        this.commandSnapshot = this.dataSnapshot.commands;
        this.eventSnapshot = this.dataSnapshot.events;
        // 循环snapshot的值，将blockName改成title，id改成value然后返回
        const blockSnapshot = this.dataSnapshot.blocks.map(item => {
          return {
            id: item.id,
            key: item.id,
            value: item.id,
            title: item.blockName,
            tag: item.tag,
            isDefault: item.isDefault
          }
        });
        this.blockSnapshot = blockSnapshot;
        this.dataTree = blockSnapshot;
        // 选中默认的模块
        let defaultItem = this.dataTree.find(item => item.isDefault === 1);
        if (!validatenull(defaultItem)) {
          this.$refs.tree.setCurrentKey(defaultItem.key);
          this.blockId = defaultItem.key;
          this.dataProperty = this.propertySnapshot.filter(item => item.blockId === defaultItem.key);
          this.matchPropertyLatest(this.dataProperty);
        }
      });
    },
    onLoadPropertyHistory(page, params = {}) {
      this.loading = true;
      let values = {
        ...params,
        deviceId: this.deviceId,
        identifier: this.propertyIdentifierId,
      };
      getPropertyHistory(page.currentPage, page.pageSize, values).then(res => {
        const data = res.data.data;
        this.pagePropertyHistory.total = data.total;
        this.dataPropertyHistory = data.records.map(record => {
          return {
            ...record, // 复制原有的record中的所有字段
            time: func.formatDateTime(record.time), // 更新time字段
            actualValue: record[this.propertyIdentifierId]
          };
        });
        this.loading = false;
      });
    },
    onLoadCommand(page, params = {}) {
      this.loading = true;
      let values = {
        ...params,
        deviceId: this.deviceId,
      };
      getCommandHistory(page.currentPage, page.pageSize, values).then(res => {
        const data = res.data.data;
        this.pageCommand.total = data.total;
        this.dataCommand = data.records.map(record => {
          return {
            ...record, // 复制原有的record中的所有字段
            time: func.formatDateTime(record.time) // 更新time字段
          };
        });
        this.loading = false;
      });
    },
    onLoadEvent(page, params = {}) {
      this.loading = true;
      let values = {
        ...params,
        deviceId: this.deviceId,
      };
      getEventHistory(page.currentPage, page.pageSize, values).then(res => {
        const data = res.data.data;
        this.pageEvent.total = data.total;
        this.dataEvent = data.records.map(record => {
          return {
            ...record, // 复制原有的record中的所有字段
            time: func.formatDateTime(record.time) // 更新time字段
          };
        });
        this.loading = false;
      });
    },
  }
};
</script>

<style>
.margin-node {
  margin-left: 12px;
}

.margin-icon {
  margin-right: 6px;
}
</style>
